package com.zp.util;

import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;

/**
 * deal with JOSN conversion between String and Object
 * 
 * @since 1.0
 * 
 * @version 1.0
 * 
 * @author chenlijun08@gmail.com
 * 
 * @date 2014/1/21
 * 
 */
public class JSONUtil {

	private static final Log logger = LogFactory.getLog(JSONUtil.class);
	private ObjectMapper objectMapper = null;
	private JsonGenerator jsonGenerator = null;
	private static JSONUtil jsonUtil = new JSONUtil();
	private Writer output = new StringWriter();

	public JSONUtil() {
		init();

	}

	/**
	 * initial the jsonGenerator
	 */
	public void init() {
		objectMapper = new ObjectMapper();
		try {
			jsonGenerator = objectMapper.getJsonFactory().createJsonGenerator(
					output);
		} catch (IOException e) {
			logger.error("IO exception");
			e.printStackTrace();
		}
	}

	/**
	 * get single instance of JSONUtil
	 * 
	 * @return JSONUtil
	 */
	public static JSONUtil getInstance() {
		if (jsonUtil == null) {
			jsonUtil = new JSONUtil();
		}
		return jsonUtil;
	}

	/**
	 * covert object to JSON String
	 * 
	 * @param o
	 * @return String
	 */
	public String convertObjectToJSON(Object o) {
		try {

			SerializationConfig sc = objectMapper.copySerializationConfig();
			sc.with(SerializationConfig.Feature.WRITE_NULL_MAP_VALUES);
			objectMapper.writeValue(jsonGenerator, o, sc);
		} catch (JsonProcessingException e) {
			logger.error("JsonProcessingException");
			e.printStackTrace();
		} catch (IOException e) {
			logger.error("IOException");
			e.printStackTrace();
		}
		return output.toString();
	}

	/**
	 * convert complex data to JSON
	 * 
	 * @param names
	 * 
	 * @param objects
	 * 
	 * @return String
	 */
	public String convertComplexDataToJSON(String[] names, Object[] objects) {
		if (names != null && objects != null && names.length == objects.length) {
			try {
				jsonGenerator.writeStartObject();
			} catch (JsonGenerationException e1) {
				logger.error("start write object:JsonProcessingException");
				e1.printStackTrace();
			} catch (IOException e1) {
				logger.error("start write object:IOException");
				e1.printStackTrace();
			}
			for (int i = 0; i < names.length; i++) {

				try {
					jsonGenerator.writeObjectField(names[i], objects[i]);
				} catch (JsonProcessingException e) {
					logger.error("write object:JsonProcessingException");
					e.printStackTrace();
				} catch (IOException e) {
					logger.error("write object:IOException");
					e.printStackTrace();
				}

			}
			try {
				jsonGenerator.writeEndObject();
			} catch (JsonGenerationException e) {
				logger.error("end write object:JsonProcessingException");
				e.printStackTrace();
			} catch (IOException e) {
				logger.error("end write object:IOException");
				e.printStackTrace();
			}
		} else {
			logger.error("please check the parameters whether its null or the length of objects whether it's equal");
		}
		return output.toString();

	}

	/**
	 * convert JSON String to Object
	 * 
	 * @param jsonContext
	 * 
	 * @param clssz
	 * 
	 * @return T
	 */
	public <T> T convertJSONToObject(String jsonContext, Class<T> clssz) {
		T o = null;
		try {
			o = objectMapper.readValue(jsonContext, clssz);
		} catch (JsonParseException e) {
			logger.error("JsonParseException");
			e.printStackTrace();
		} catch (JsonMappingException e) {
			logger.error("JsonMappingException");
			e.printStackTrace();
		} catch (IOException e) {
			logger.error("IOException");
			e.printStackTrace();
		}
		return o;

	}

	public String decorateJSONString(String jsonStr) {
		return jsonStr.replace("\"", "\\\"");

	}

	/**
	 * destroy jsonGenerator
	 */
	public void destroy() {
		if (jsonGenerator != null) {
			try {
				jsonGenerator.flush();
				if (!jsonGenerator.isClosed()) {
					jsonGenerator.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
			jsonGenerator = null;
			objectMapper = null;
		}
	}
}
